package com.lab.system.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.lab.common.core.domain.entity.SysUser;
import com.lab.common.core.domain.model.LoginUser;
import com.lab.common.enums.AuditEnum;
import com.lab.common.enums.LabBorrowStatus;
import com.lab.common.utils.DateUtils;
import com.lab.system.domain.ExperimentCourse;
import com.lab.system.domain.Lab;
import com.lab.system.domain.Reservations;
import com.lab.system.mapper.ExperimentCourseMapper;
import com.lab.system.mapper.LabMapper;
import com.lab.system.mapper.ReservationsMapper;
import com.lab.system.mapper.SysUserMapper;
import com.lab.system.service.IExperimentCourseService;
import com.lab.system.service.IReservationsService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 实验预约Service业务层处理
 *
 * @author cf
 * @date 2025-02-10
 */
@Service
public class ReservationsServiceImpl implements IReservationsService {


    @Autowired
    private ReservationsMapper reservationsMapper;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private ExperimentCourseMapper courseMapper;
    @Autowired
    private LabMapper labMapper;
    @Autowired
    private IExperimentCourseService courseService;

    /**
     * 查询实验预约
     *
     * @param id 实验预约主键
     * @return 实验预约
     */
    @Override
    public Reservations selectReservationsById(Long id) {
        return reservationsMapper.selectReservationsById(id);
    }

    /**
     * 查询实验预约列表
     *
     * @return 实验预约
     */
    @Override
    public List<Reservations> selectReservationsList(Reservations reservationsQO, LoginUser loginUser) {
        if (loginUser != null) {
            // 权限控制
            List<ExperimentCourse> courseList = courseService.selectExperimentCourseList(new ExperimentCourse(), loginUser);
            List<Long> courseIds = courseList.stream().map(ExperimentCourse::getId).collect(Collectors.toList());
            reservationsQO.setCourseIds(courseIds);
        }

        List<Reservations> reservationsList = reservationsMapper.selectReservationsList(reservationsQO);
        List<Long> userIds = new ArrayList<>();
        List<Long> labIds = new ArrayList<>();
        List<Long> courseIds = new ArrayList<>();
        for (Reservations reservations : reservationsList) {
            userIds.add(reservations.getUserId());
            userIds.add(reservations.getInstructorId());
            labIds.add(reservations.getLabId());
            courseIds.add(reservations.getCourseId());
        }
        // 批量根据id查询
        List<SysUser> sysUsers = userMapper.selectUserByIds(userIds);
        // 收集为map
        Map<Long, SysUser> userMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, sysUser -> sysUser));
        List<ExperimentCourse> courses = courseMapper.selectExperimentCourseByIds(courseIds);
        Map<Long, ExperimentCourse> courseMap = courses.stream().collect(Collectors.toMap(ExperimentCourse::getId, experimentCourse -> experimentCourse));
        Lab lab = new Lab();
        lab.setLabIds(labIds);
        List<Lab> labs = labMapper.selectLabList(lab);
        Map<Long, String> labMap = labs.stream().collect(Collectors.toMap(Lab::getId, Lab::getLabName));
        reservationsList.forEach(x -> {
            x.setUserName(userMap.get(x.getUserId()).getUserName());
            x.setLabName(labMap.get(x.getLabId()));
            x.setCourseName(courseMap.get(x.getCourseId()).getCourseName());
            SysUser sysUser = userMap.get(x.getInstructorId());
            x.setInstructorName(Objects.isNull(sysUser) ? "" : sysUser.getUserName());
            x.setStatusDesc(LabBorrowStatus.getLabStatus(x.getStatus().intValue()).getInfo());
            x.setAuditDesc(AuditEnum.getLabStatus(x.getAudit()).getInfo());
        });
        return reservationsList;
    }

    /**
     * 新增实验预约
     *
     * @param reservations 实验预约
     * @return 结果
     */
    @Override
    public int insertReservations(Reservations reservations) {
        ExperimentCourse course = courseMapper.selectExperimentCourseById(reservations.getCourseId());
        if (course == null) {
            throw new RuntimeException("实验课程不存在");
        }
        reservations.setStartTime(course.getStartTime());
        reservations.setEndTime(course.getEndTime());
        reservations.setStatus(0L);
        // 实验时长(分钟)
        reservations.setDuration(DateUtil.between(reservations.getStartTime(), reservations.getEndTime(), DateUnit.MINUTE));
        return reservationsMapper.insertReservations(reservations);
    }

    /**
     * 修改实验预约
     *
     * @param reservations 实验预约
     * @return 结果
     */
    @Override
    public int updateReservations(Reservations reservations) {
        ExperimentCourse course = courseMapper.selectExperimentCourseById(reservations.getCourseId());
        if (course == null) {
            throw new RuntimeException("实验课程不存在");
        }
        reservations.setStartTime(course.getStartTime());
        reservations.setEndTime(course.getEndTime());
        // 实验时长(分钟)
        reservations.setDuration(DateUtil.between(reservations.getStartTime(), reservations.getEndTime(), DateUnit.MINUTE));
        return reservationsMapper.updateReservations(reservations);
    }

    /**
     * 批量删除实验预约
     *
     * @param ids 需要删除的实验预约主键
     * @return 结果
     */
    @Override
    public int deleteReservationsByIds(Long[] ids) {
        return reservationsMapper.deleteReservationsByIds(ids);
    }

    /**
     * 删除实验预约信息
     *
     * @param id 实验预约主键
     * @return 结果
     */
    @Override
    public int deleteReservationsById(Long id) {
        return reservationsMapper.deleteReservationsById(id);
    }

    @Override
    public List<Reservations> selectReservationsListByUser(Reservations reservationsQO, Long userId) {
        reservationsQO.setUserId(userId);
        List<Reservations> reservationsList = reservationsMapper.selectReservationsList(reservationsQO);
        List<Long> userIds = new ArrayList<>();
        List<Long> labIds = new ArrayList<>();
        List<Long> courseIds = new ArrayList<>();
        for (Reservations reservations : reservationsList) {
            userIds.add(reservations.getUserId());
            userIds.add(reservations.getInstructorId());
            labIds.add(reservations.getLabId());
            courseIds.add(reservations.getCourseId());
        }
        // 批量根据id查询
        List<SysUser> sysUsers = userMapper.selectUserByIds(userIds);
        // 收集为map
        Map<Long, SysUser> userMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, sysUser -> sysUser));
        List<ExperimentCourse> courses = courseMapper.selectExperimentCourseByIds(courseIds);
        Map<Long, ExperimentCourse> courseMap = courses.stream().collect(Collectors.toMap(ExperimentCourse::getId, experimentCourse -> experimentCourse));
        Lab lab = new Lab();
        lab.setLabIds(labIds);
        List<Lab> labs = labMapper.selectLabList(lab);
        Map<Long, String> labMap = labs.stream().collect(Collectors.toMap(Lab::getId, Lab::getLabName));
        reservationsList.forEach(x -> {
            x.setUserName(userMap.get(x.getUserId()).getUserName());
            x.setLabName(labMap.get(x.getLabId()));
            x.setCourseName(courseMap.get(x.getCourseId()).getCourseName());
            x.setInstructorName(userMap.get(x.getInstructorId()).getUserName());
        });
        return reservationsList;
    }

    @Override
    public List<Reservations> selectReservationsByIds(List<Long> reservationIds) {
        if (CollectionUtils.isEmpty(reservationIds)) {
            return new ArrayList<>();
        }
        return reservationsMapper.selectReservationsByIds(reservationIds);
    }

    @Override
    public List<Reservations> getAllAudit(Integer code) {
        Reservations reservations = new Reservations();
        reservations.setAudit(code);
        reservations.setStatus(LabBorrowStatus.USE_AUTO.getCode().longValue());
        return selectReservationsList(reservations,null);
    }
}
